package com.example.video.admin_server.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.video.admin_server.entity.SysMenu;
import com.example.video.admin_server.entity.SysRole;
import com.example.video.admin_server.entity.SysRoleMenu;
import com.example.video.admin_server.entity.vo.MenuDetailVo;
import com.example.video.admin_server.mapper.SysMenuMapper;
import com.example.video.admin_server.service.ISysMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.video.admin_server.service.ISysRoleMenuService;
import com.example.video.admin_server.service.ISysRoleService;
import com.example.video.common.Constant;
import com.example.video.common.util.SysUserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 * 系统菜单表 服务实现类
 * </p>
 *
 * @author yj
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {

    @Autowired
    private ISysRoleMenuService iSysRoleMenuService;

    @Autowired
    private ISysRoleService iSysRoleService;

    @Autowired
    private SysMenuMapper sysMenuMapper;

    @Override
    public List<MenuDetailVo> getSelfMenus() {
        List<SysRole> roles = SysUserUtils.getRoles();
        List<Integer> roleIds = new ArrayList<>();
        for (SysRole role : roles){
            roleIds.add(role.getId());
        }
        List<SysMenu> menus = iSysRoleMenuService.findMenusByRoles(roleIds, Constant.Status.ENABLE.value);
        Set<SysMenu> menuSet = new LinkedHashSet<>(menus);
        List<MenuDetailVo> menuDetailVos = getMenuDetailVos(new ArrayList<>(menuSet));
        return menuDetailVos;
    }

    @Override
    public List<MenuDetailVo> getMenuDetailVoList(SysMenu sysMenu) {
        List<SysMenu> list = this.list(new QueryWrapper<>(sysMenu.setStatus(Constant.Status.ENABLE.value)));
        List<MenuDetailVo> menuDetailVos = getMenuDetailVos(list);
        return menuDetailVos;
    }

    @Override
    public Page getPaginationList(Page<SysMenu> SysMenuPage, SysMenu sysMenu) {
        // 分页查询父级菜单
        sysMenu.setParentId(0);
        SysMenuPage.setOrders(Arrays.asList(new OrderItem().setColumn("sort").setAsc(true)));
        Page page = this.page(SysMenuPage, new QueryWrapper<>(sysMenu));
        List<SysMenu> records = page.getRecords();

        // 通过父级id批量递归查询所有子级
        if (records.size() > 0) {
            List<Integer> list = new ArrayList<>();
            for (SysMenu menu : records){
                list.add(menu.getId());
            }
            List<MenuDetailVo> recursionByParentIds = sysMenuMapper.findRecursionByParentIds(list);
            List<MenuDetailVo> result = new ArrayList<>();
            for (SysMenu menu : records){
                MenuDetailVo parent = new MenuDetailVo(menu);
                parent.setChildren(new ArrayList<>());
                result.add(parent);
                for (MenuDetailVo child : recursionByParentIds){
                    if (parent.getId().equals(child.getParentId())) {
                        parent.getChildren().add(child);
                    }
                }
            }
            page.setRecords(result);
        }
        return page;
    }

    @Override
    @Transactional
    public boolean add(SysMenu sysMenu) {
        boolean save = this.save(sysMenu);
        return save;
    }

    @Override
    public MenuDetailVo getDetails(Integer id) {
        SysMenu byId = this.getById(id);
        List<Integer> parents = new ArrayList<>();
        getParentIds(byId,parents);
        MenuDetailVo menuDetailVo = new MenuDetailVo(byId);
        menuDetailVo.setParents(parents);
        return menuDetailVo;
    }

    @Override
    @Transactional
    public boolean del(Integer id) {
        SysMenu sysMenu = new SysMenu();
        sysMenu.setParentId(id);
        List<SysMenu> list = this.list(new QueryWrapper<>(sysMenu));
        if (list.size() > 0){
            throw new RuntimeException("请先删除该菜单下的子菜单，或修改到其他目录下");
        }
        boolean b1 = this.removeById(id);
        SysRoleMenu sysRoleMenu = new SysRoleMenu();
        sysRoleMenu.setMenuId(id);
        boolean b = iSysRoleMenuService.remove(new QueryWrapper<>(sysRoleMenu));
        return b && b1;
    }

    /**
     * 获取菜单所有父级
     */
    private void getParentIds(SysMenu sysMenu,List parentIds){
        if (!Constant.ROOT_ID.equals(sysMenu.getParentId())){
            SysMenu byId = this.getById(sysMenu.getParentId());
            if (byId != null) {
                parentIds.add(0, byId.getId());
                getParentIds(byId, parentIds);
            }
        }
    }

    private List<MenuDetailVo> getMenuDetailVos(List<SysMenu> menus){
        List<MenuDetailVo> parentPageMenus = new ArrayList<>();
        for (SysMenu menu : menus){
             if (menu.getParentId() == 0 ){
                MenuDetailVo parent = new MenuDetailVo(menu);
                recursionGetChildren( menus, parent);
                parentPageMenus.add(parent);
            }
        }
        return parentPageMenus;
    }

    /**
     * 递归获取子菜单
     */
    private void recursionGetChildren(List<SysMenu> menus, MenuDetailVo parent){
        for (SysMenu menu : menus){
            if (menu.getParentId().equals(parent.getId())){
                List<MenuDetailVo> children = parent.getChildren();
                if (children == null){
                    children = new ArrayList<>();
                    parent.setChildren(children);
                }
                MenuDetailVo childMenu = new MenuDetailVo(menu);
                children.add(childMenu);
                recursionGetChildren(menus, childMenu);
            }
        }
    }
}
